/* enum */
import { RootVuexPropertyEnum } from '@src/modules/account/roleService/model/enum/VuexPropertyEnum'
import { ElementClassNameEnum } from '@src/modules/account/roleService/model/enum/ClassNameEnum'
/* model */
import ElementLoadingOption from '@src/modules/account/roleService/model/element/ElementLoadingOption'
/* vue */
import { watch, computed, ComputedRef } from "vue"
/* element */
import { Loading } from 'element-ui'
/* vuex */
import { useStore } from '@src/modules/account/roleService/store/hooks'
import StoreStateType from '@src/modules/account/roleService/store/model'
/* util */
import Log from '@src/util/log'

export type UseLoadingReturnType = {
  // 加载状态
  loading: ComputedRef<boolean>;
  // 是否在加载中
  isLoading: ComputedRef<boolean>;
  // 设置加载状态
  setLoading: (loading?: boolean) => void;
  // 清除加载状态
  clearLoading: VoidFunction;
}

let loadingInstance: { close: Function } | null = null

export default function useLoading(elementLoadingOption?: Partial<ElementLoadingOption>): UseLoadingReturnType {
  // 数据存储器
  const store = useStore<StoreStateType>()
  // 加载状态
  const loading: ComputedRef<boolean> = computed(() => store.state.loading)
  // 是否正在加载
  const isLoading: ComputedRef<boolean> = computed(() => loading.value)
  // 默认提示配置
  const defaultElementLoadingOption: ElementLoadingOption = new ElementLoadingOption();
  // 提示配置
  const loadingOption: ElementLoadingOption = Object.assign({}, defaultElementLoadingOption, elementLoadingOption);
  
  const setLoading = (value = true) => {
    store.commit(RootVuexPropertyEnum.SetLoading, value)
  }
  
  const clearLoading = () => {
    setLoading(false)
  }
  
  watch(loading, (newValue: boolean) => {
    // 是否显示加载状态
    const isShowLoading: boolean = newValue
    
    if (isShowLoading) {
      showLoading(loadingOption)
    } else {
      hideLoading()
    }
    
  })
  
  return {
    loading,
    isLoading,
    setLoading,
    clearLoading
  }
}

function showLoading(loadingOption: ElementLoadingOption): void {
  loadingInstance = Loading.service(loadingOption)
}

function hideLoading(): void {
  loadingInstance && loadingInstance.close()
  removeElementLoadingInstance()
}

function removeElementLoadingInstance() {
  try {
    const element = document.querySelector(ElementClassNameEnum.ElLoadingMask)
    element && document.body.removeChild(element)
  } catch (error) {
    Log.error(error, removeElementLoadingInstance.name)
  }
}